---
sidebar_position: 7
---

# Шаг 5. Упаковка приложения в Docker-контейнер

Для дальнейшего продвижения нам потребуется упаковать приложение в Docker-контейнер.

Не забудьте удалить предыдущий контейнер `jaeger`:

```bash
docker stop jaeger
```

Создадим следующую директорию с содержимым:

```bash
observability
├── app
│   ├── .gitignore
│   ├── app.py
│   ├── Dockerfile
│   └── requirements.txt
├── .gitignore
└── docker-compose.yaml
```

Файл `app/.gitignore` и `.gitignore` можно заполнить по примеру [отсюда](https://github.com/github/gitignore/blob/main/Python.gitignore).

Файл `app/app.py` с учетом адаптации под контейнер выглядит следующим образом:

```python
# highlight-start
import os
# highlight-end
from flask import Flask
from random import randint
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.trace.export import ConsoleSpanExporter
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.sdk.resources import SERVICE_NAME, Resource


provider = TracerProvider()
processor = BatchSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
trace.set_tracer_provider(
    TracerProvider(
        # highlight-next-line
        resource=Resource.create({SERVICE_NAME: os.environ.get('APP_SERVICE_NAME',"my-python-service")})
    )
)
# highlight-start
jaeger_exporter = JaegerExporter(
    agent_host_name=os.environ.get('JAEGER_EXPORTER_HOST_NAME', "localhost"),
    agent_port=int(os.environ.get('JAEGER_EXPORTER_PORT', 6831)),
)
# highlight-end
trace.get_tracer_provider().add_span_processor(
    BatchSpanProcessor(jaeger_exporter)
)

tracer = trace.get_tracer(__name__)

app = Flask(__name__)


def roll():
    return randint(1, 6)


@app.route("/rolldice")
def roll_dice():
    with tracer.start_as_current_span("server_request"):
        return str(roll())


# highlight-start
if __name__ == "__main__":
    host = os.environ.get('APP_HOST_NAME', "0.0.0.0")
    port = int(os.environ.get('APP_PORT', 5000))
    app.run(debug=True, host=host, port=port)
# highlight-end

```

Файл `app/Dockerfile` выглядит следующим образом:

```Dockerfile
FROM python:3.12-slim-bookworm
COPY ./requirements.txt /app/requirements.txt
WORKDIR /app
RUN pip install -r requirements.txt
COPY . /app
EXPOSE 5000
CMD ["python", "app.py" ]
```

Файл `app/requirements.txt` выглядит следующим образом:

```text
Flask==3.0.0
opentelemetry-sdk==1.21.0
opentelemetry-exporter-jaeger==1.21.0
```

Файл `docker-compose.yaml` выглядит следующим образом:

```docker
services:
  app:
    image: iu5devops/app
    build:
      context: ./app
      dockerfile: Dockerfile
    container_name: iu5devops-app
    networks:
      - iu5devops
    ports:
      - 8080:5000
    environment:
      - APP_SERVICE_NAME=iu5devops-app
      - JAEGER_EXPORTER_HOST_NAME=iu5devops-jaeger
      - JAEGER_EXPORTER_PORT=6831

  jaeger:
    image: jaegertracing/all-in-one
    container_name: iu5devops-jaeger
    networks:
      - iu5devops
    ports:
      - 16686:16686
      
networks:
  iu5devops:
```

Чтобы поднять нашу инфраструктуру, в директории `observability` выполните:

```bash
docker compose build
docker compose up -d
```

Убедитесь, что Jaeger в контейнере собирает трассировку. Для этого выполните запрос к [http://localhost:8080/rolldice](http://localhost:8080/rolldice) несколько раз. Посмотрите трассировку в Jaeger UI [http://localhost:16686/](http://localhost:16686/).
